#include "IssuerLiquidity.h"

#include <QDateTime>

#include "BondContainer.h"
#include "SSVContainer.h"

CIssuerLiquidity& CIssuerLiquidity::instance() {
  static CIssuerLiquidity s_il;
  return s_il;
}

CIssuerLiquidity::CIssuerLiquidity() {
  m_nToday = 0;
  ClearData();
}

CIssuerLiquidity::~CIssuerLiquidity() {}

void CIssuerLiquidity::UpdateLiquidity(xQBIssuerLiquidityFullAck_c* pAck) {
  std::lock_guard<std::mutex> locker(m_mutex);
  if (!pAck) return;
  string stCombKey;
  for (auto itr = pAck->m_List.begin(); itr != pAck->m_List.end(); ++itr) {
    m_mapLiquidity[itr->m_IssuerCode] = *itr;
  }
}

bool CIssuerLiquidity::GetLiquidity(int bondIndex,
                                    xQBIssuerLiquidityUnit& unit) {
  if (!CBondContainer::instance().IsValidIndex(bondIndex)) return false;
  const CBondInfo& bi = CBondContainer::instance().ElementAtR(bondIndex);
  const char* szIssuerCode = bi.GetIssuerCode();
  std::lock_guard<std::mutex> locker(m_mutex);
  const auto& it = m_mapLiquidity.find(szIssuerCode);
  if (it != m_mapLiquidity.end()) {
    unit = it->second;
    return true;
  }
  return false;
}

bool CIssuerLiquidity::GetLiquidity(const char* sIssuerCode,
                                    xQBIssuerLiquidityUnit& unit) {
  if (!sIssuerCode) return false;
  std::lock_guard<std::mutex> locker(m_mutex);
  const auto& it = m_mapLiquidity.find(sIssuerCode);
  if (it != m_mapLiquidity.end()) {
    unit = it->second;
    return true;
  }
  return false;
}

bool CIssuerLiquidity::ClearData() {
  std::lock_guard<std::mutex> locker(m_mutex);
  bool cleared = false;
  QDateTime ctm = QDateTime::fromTime_t(CSSVContainer::GetServerTime());
  int nToday =
      ctm.date().year() * 10000 + ctm.date().month() * 100 + ctm.date().day();
  if (nToday != m_nToday) {
    m_nToday = nToday;
    m_mapLiquidity.clear();
    cleared = true;
  }
  return cleared;
}

bool CIssuerLiquidity::CheckLiquidity(int bondIndex, const BLHCONDITION& blh) {
  if (blh.sIssuerLiquidity[0] == '\0') return true;  // all
  if (!CBondContainer::instance().IsValidIndex(bondIndex)) return false;
  const CBondInfo& bi = CBondContainer::instance().ElementAtR(bondIndex);
  const char* szIssuerCode = bi.GetIssuerCode();
  if (!szIssuerCode) return false;

  const auto& it = m_mapLiquidity.find(szIssuerCode);
  if (it == m_mapLiquidity.end()) return false;

  const char* p = blh.sIssuerLiquidity;
  int sz = sizeof(blh.sIssuerLiquidity);
  int n = 0;
  while (*p != '\0' && n < sz) {
    if (it->second.m_liquidLevel[0] == *p) return true;
    p++;
    n++;
  }
  return false;
}
